#ifndef __M_UTIL_H__
#define __M_UTIL_H__
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
#include <memory>
#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>
#include "Log.hpp"
class mysql_util
{
public:
    static MYSQL *mysql_create(const std::string host,
                               const std::string username,
                               const std::string password,
                               const std::string dbname,
                               int port)
    {
        MYSQL *mysql = mysql_init(nullptr);
        if (mysql == nullptr)
        {
            ELOG("mysql_create failed : %s", mysql_error(mysql));
            mysql_close(mysql);
            return nullptr;
        }
        if (mysql_real_connect(mysql, host.c_str(), username.c_str(), password.c_str(), dbname.c_str(), port, nullptr, 0) == nullptr)
        {
            ELOG("mysql_real_connect failed : %s", mysql_error(mysql));
            mysql_close(mysql);
            return nullptr;
        }
        if (mysql_set_character_set(mysql, "utf8") != 0)
        {
            ELOG("mysql_set_character_set failed : %s", mysql_error(mysql));
            mysql_close(mysql);
            return nullptr;
        }
        return mysql;
    }
    static bool mysql_execute(MYSQL *mysql, const std::string &sql)
    {
        int ret = mysql_query(mysql, sql.c_str());
        if (ret != 0)
        {
            ELOG("%s", sql.c_str());
            ELOG("mysql_query failed : %s", mysql_error(mysql));
            mysql_close(mysql);
            return false;
        }
        return true;
    }
    static void mysql_destroy(MYSQL *mysql)
    {
        if (mysql)
        {
            mysql_close(mysql);
        }
    }
};

class json_util
{
public:
    static bool serialize(const Json::Value &root, std::string &str)
    {
        Json::StreamWriterBuilder swb;
        swb.settings_["emitUTF8"] = true; // 禁用 Unicode 转义，直接输出 UTF-8
        std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
        std::stringstream ss;
        if (sw->write(root, &ss) != 0)
        {
            ELOG("serialize failed");
            return false;
        }

        str = ss.str();
        return true;
    }
    static bool deserialize(const std::string &str, Json::Value &root)
    {
        Json::CharReaderBuilder crb;
        std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
        std::string err;
        if (cr->parse(&str[0], &str[0] + str.size(), &root, &err) == false)
        {
            ELOG("deserialize failed : %s", err.c_str());
            return false;
        }
        return true;
    }
};
class string_util
{
public:
    // 127..0.0.1
    static size_t split(const std::string &str, const std::string &sep, std::vector<std::string> &strset)
    {
        int index = 0;
        while (index < str.size())
        {
            int pos = str.find(sep, index);
            if (pos == std::string::npos)
            {
                strset.push_back(str.substr(index));
                break;
            }
            if (pos == index)
            {
                index = pos + sep.size();
                continue;
            }
            strset.push_back(str.substr(index, pos - index));
            index = pos + sep.size();
        }
        return strset.size();
    }
};
class file_util
{
public:
    static bool open(const std::string &filename, std::string &content)
    {
        std::ifstream f(filename.c_str(), std::ios::binary);
        if (f.is_open() == false)
        {
            ELOG("open file failed");
            return false;
        }
        f.seekg(0, std::ios_base::end);
        int sz = f.tellg();
        ILOG("sz: %d filename:%s", sz, filename.c_str());
        f.seekg(0, std::ios_base::beg);
        content.resize(sz);
        f.read(&content[0], sz);
        f.close();
        return true;
    }
};
#endif